<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title></title>
</head>
<body>
<script type="text/javascript">
    var Person = function() {

    };
    var man = new Person();
    var woman = new Person();

    /*
    * 当使用一个构造函数以new操作符来创建多个对象时，应该获得指向完全相同的对象的新指针
    * 方式：当调用构造函数时，缓存this对象，第二次调用时直接返回this，三种方案：
    * 1、用全局变量缓存，不可取
    * 2、给构造函数设置一个属性来缓存，缺点是外部能访问，易被更改
    * 3、将实例包装在闭包中
    *  */
    // eg:
    function Universe1() {
        if(typeof Universe1.instance === "object") {
            return Universe1.instance;
        }
        // 其他部分

        // 缓存
        Universe1.instance = this;
    }

    // 方式3：
    function Universe2() {
        var instance = this;

        // 其他部分

        // 重写构造函数
        Universe2 = function() {
            return instance;
        };
    }
    /*
    * 上述方法有一个缺点在于：重写构造函数时会丢失在初始定义和重定义之间添加到它里的属性  ---------此处个人理解应该是在第一次调用构造函数后，所有给构造函数定义的属性都会无效，包括原型属性
    * 在这期间，任何添加到构造函数原型中的对象都不会存在指向原始实现所创建实例的活动链接  ---------重新定后的构造函数已不会返回一个真正意义由自己构造的实例
    * */
    Universe2.prototype.nothing = true;
    var u1 = new Universe2();
    Universe2.prototype.something = true;
    var u2 = new Universe2();
    Universe2.prototype.thing = true;
    console.log(u1.nothing);
    console.log(u1.something);
    console.log(u1.thing);
    console.log(u2.nothing);
    console.log(u1.something);
    console.log(u1.thing);
    console.log(u1.constructor.name);
    console.log(u1.constructor === Universe2);
    /*
    * 因此对上述的改进
    * */
    function Universe() {
        var instance = null;
        Universe = function() {
            return instance;
        };

        // 保留原型属性
        Universe.prototype = this;

        // 构造一个重写构造函数后的新实例
        instance = new Universe();           // ---------此步很关键，其实第一次返回的实例，已经是重写后的构造函数的实例

        // 重置构造函数指针
        instance.constructor = Universe;

        // 其他功能

        return instance;       // ---------此处一定要返回instance，不能返回，否则构造的实例不是指向同一实例

    }
    // test:
    Universe.prototype.nothing = true;
    var u1 = new Universe();
    Universe.prototype.something = true;
    var u2 = new Universe();
    Universe.prototype.thing = true;
    console.log(u1.nothing);
    console.log(u1.something);
    console.log(u1.thing);
    console.log(u2.nothing);
    console.log(u1.something);
    console.log(u1.thing);
    console.log(u1.constructor.name);
    console.log(u1.constructor === Universe);

    /*
    * 第4种实现方式：  --------此方式不用重写构造函数
    * */

    var Universe3 = (function() {
        var instance = null;
        return function(){
            if(instance) {
                return instance;
            }
            instance = this;

            // 其他功能

        };
    }());

    // test:
    Universe3.prototype.nothing = true;
    var u1 = new Universe3();
    Universe3.prototype.something = true;
    var u2 = new Universe3();
    Universe3.prototype.thing = true;
    console.log(u1.nothing);
    console.log(u1.something);
    console.log(u1.thing);
    console.log(u2.nothing);
    console.log(u1.something);
    console.log(u1.thing);
    console.log(u1.constructor.name);
    console.log(u1.constructor === Universe3);

</script>
</body>
</html>